home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / viewers / ham8_jpg.lha / ham8-jpeg / Source / ham8.c < prev    next >
C/C++ Source or Header  |  1992-12-20  |  11KB  |  460 lines

  1. /*
  2.  * ham8.c Michael Saunby   M.Saunby@reading.ac.uk
  3.  *
  4.  * Release 1.1   December 1992 A public screen plus utilities to give a pseudo
  5.  * 24 bit display on Amigas with AGA graphics (A1200 and A4000).
  6.  *
  7.  * The AGA HAM-8 mode allows 64 colours to be defined - 48 of these will be
  8.  * defined by this program (see display24.c) leaving 8 for intuition and
  9.  * client programs.
  10.  */
  11. #include <intuition/intuition.h>
  12. #include <graphics/gfxbase.h>
  13. #include <graphics/displayinfo.h>
  14. #include <intuition/screens.h>
  15. #include <dos/dosextens.h>
  16. #include <dos/rdargs.h>
  17. #include <exec/memory.h>
  18. #include <exec/types.h>
  19. #include <libraries/dos.h>
  20. #include <libraries/dosextens.h>
  21. #include <libraries/gadtools.h>
  22.  
  23. #include <clib/exec_protos.h>
  24. #include <clib/intuition_protos.h>
  25. #include <clib/graphics_protos.h>
  26. #include <clib/gadtools_protos.h>
  27. #include <clib/dos_protos.h>
  28. #include <clib/alib_protos.h>
  29.  
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32.  
  33. #include "display24.h"
  34.  
  35. /*
  36.  * If you turn this into something different feel free to change this, but if
  37.  * you don't leave it alone!!
  38.  */
  39. #define COPYRIGHT_MESSAGE "Version 1.1\nDecember 1992\n\nCopyright ⌐ 1992\n\
  40. Michael Saunby"
  41.  
  42. /*
  43.  * Template etc for ReadArgs() - Pity it can't read tooltypes
  44.  */
  45. #define TEMPLATE "W=Width/N,H=Height/N,L=LoRes/S"
  46. #define OPT_WIDTH 0
  47. #define OPT_HEIGHT 1
  48. #define OPT_LORES 2
  49. #define OPT_COUNT 3
  50.  
  51. struct IntuitionBase *IntuitionBase = NULL;
  52. struct GfxBase *GfxBase = NULL;
  53. struct Library *GadToolBase = NULL;
  54.  
  55. extern struct ExecBase *SysBase;
  56.  
  57. BOOL restart = FALSE;        /* used for resize - see main() */
  58. UWORD width, height;
  59. BOOL lores;
  60. struct Screen *screen;
  61. struct MsgPort *messageport;
  62. ULONG allocsignal;
  63.  
  64. /*
  65.  * Message structure used to get screen size changed, see main()
  66.  */
  67. struct TestMsg
  68. {
  69.   struct Message msg;
  70.   USHORT Width;
  71.   USHORT Height;
  72.   BOOL Lores;
  73. };
  74.  
  75. /*
  76.  * Easy Requester used for error messages
  77.  */
  78. struct EasyStruct failedES =
  79. {sizeof (struct EasyStruct), 0, HAM8_ALBERT_NAME,
  80.  "%s", "OK",};
  81.  
  82. /*
  83.  * Gadtools menu
  84.  */
  85. #define ABOUT 1
  86. #define QUIT 2
  87. struct NewMenu prj_menu[] =
  88. {
  89.   {NM_TITLE, "Project", 0, 0, 0, 0,},
  90.   {NM_ITEM, "About...", "?", 0, 0, (void *) ABOUT,},
  91.   {NM_ITEM, "Quit", "Q", 0, 0, (void *) QUIT,},
  92.   {NM_END, NULL, 0, 0, 0, 0,},
  93. };
  94.  
  95.  
  96. /*
  97.  * Cleanup() - Close screen and libraries before exit
  98.  */
  99. VOID Cleanup (VOID);
  100.  
  101. VOID
  102. Cleanup ()
  103. {
  104.   if (restart)
  105.     {
  106.       /*
  107.        * Failed to open screen for client. There is a message port waiting
  108.        * for a reply.
  109.        */
  110.     }
  111.   if (screen)
  112.     {
  113.       CloseScreen (screen);
  114.       FreeSignal (allocsignal);
  115.     }
  116.   if (GadToolBase)
  117.     CloseLibrary (GadToolBase);
  118.   if (IntuitionBase)
  119.     CloseLibrary ((struct Library *) IntuitionBase);
  120.   if (GfxBase)
  121.     CloseLibrary ((struct Library *) GfxBase);
  122.  
  123. }
  124.  
  125. /*
  126.  * Quit() - Cleanup and exit on error
  127.  */
  128. VOID Quit ();
  129.  
  130. VOID
  131. Quit (char whytext[], UBYTE failcode)
  132. {
  133.   EasyRequest (NULL, &failedES, NULL, whytext);
  134.   Cleanup ();
  135.   DeletePort (messageport);
  136.   exit (failcode);
  137. }
  138.  
  139. /*
  140.  * CreateScreen() - Main function, build and open a public screen
  141.  */
  142. VOID
  143. CreateScreen ( /* USES GLOBALS width, height, lores, restart */ )
  144. {
  145.   ULONG modeID = HIRESHAMLACE_KEY;
  146.   DisplayInfoHandle displayhandle;
  147.   struct DimensionInfo dimensioninfo;
  148.  
  149.   UWORD maxdepth;
  150.   ULONG soerror = NULL;
  151.   ULONG signal, wsignal, lastsignal;
  152.   ULONG psignal;        /* Message port - Another copy of program
  153.                  * started */
  154.   struct Task *task;
  155.   BOOL abort = FALSE, closedown = FALSE;
  156.   UWORD oldstatus;
  157.   struct IntuiMessage *msg;
  158.   static struct TestMsg *newdims_msg;    /* MUST be static, reply is delayed! */
  159.   struct Window *window;
  160.   struct Menu *menu;
  161.   void *vi;
  162.  
  163.  
  164.   if (lores)
  165.     modeID = HAM_KEY;
  166.  
  167.   if ((GfxBase =
  168.        (struct GfxBase *) OpenLibrary ("graphics.library", 36)) == NULL)
  169.     Quit ("graphics.library is too old <V36", 25);
  170.  
  171.   if ((IntuitionBase =
  172.     (struct IntuitionBase *) OpenLibrary ("intuition.library", 36)) == NULL)
  173.     Quit ("intuition.library is too old <V36", 25);
  174.  
  175.   if ((displayhandle = FindDisplayInfo (modeID)) == NULL)
  176.     Quit ("modeID not found in display database", 25);
  177.  
  178.   if (GetDisplayInfoData (displayhandle, (UBYTE *) & dimensioninfo,
  179.                sizeof (struct DimensionInfo), DTAG_DIMS, NULL) == 0)
  180.     Quit ("mode dimension info not available", 25);
  181.  
  182.   /*
  183.    * Public screen needs a signal and pointer to this task.
  184.    */
  185.   if ((allocsignal = AllocSignal (-1)) == -1)
  186.     Quit ("could not allocate signal", 25);
  187.  
  188.   lastsignal = 1 << allocsignal;
  189.  
  190.   task = (struct Task *) & ((struct Process *) FindTask (NULL))->pr_Task;
  191.  
  192.   /*
  193.    * MaxDepth will always be 8 for Ham8 mode.  But it can't hurt.
  194.    */
  195.   maxdepth = dimensioninfo.MaxDepth;
  196.   /*
  197.    * If you always want a standard size just use SA_Overscan, OSCAN_TEXT
  198.    * etc.  I have to get the dimensions from dimensioninfo because I always
  199.    * set the width and height.
  200.    */
  201.   if (width == 0)
  202.     width = dimensioninfo.TxtOScan.MaxX - dimensioninfo.TxtOScan.MinX;
  203.   if (height == 0)
  204.     height = dimensioninfo.TxtOScan.MaxY - dimensioninfo.TxtOScan.MinY;
  205.  
  206.   /*
  207.    * Screen is based on workbech to give a familiar look. Could possibly
  208.    * cause problems is the default is a 256 colour WB, must try that
  209.    * sometime and see what happens.
  210.    */
  211.   if ((screen = OpenScreenTags (NULL,
  212.                 SA_LikeWorkbench, TRUE,    /* see above */
  213.                 SA_Overscan, OSCAN_TEXT,
  214.                 SA_AutoScroll, TRUE,
  215.                 SA_DisplayID, modeID,
  216.                 SA_Depth, (UBYTE) maxdepth,
  217.                 SA_Width, width,
  218.                 SA_Height, height,
  219.                 SA_Title, HAM8_ALBERT_NAME,
  220.                 SA_PubName, HAM8_ALBERT_NAME,
  221.                 SA_PubSig, allocsignal,
  222.                 SA_PubTask, task,
  223.                 SA_ErrorCode, &soerror,
  224.                 SA_SharePens, TRUE,
  225.                 TAG_END)) == NULL)
  226.     {
  227.       /*
  228.        * There are many reasons why this might fail, though on an AGA
  229.        * machine only NOCHIPMEM is likely.  The other tests are worth
  230.        * keeping for when this code is next used.
  231.        */
  232.       switch (soerror)
  233.     {
  234.     case OSERR_NOCHIPS:
  235.       Quit ("Amiga custom chips not AGA", 25);
  236.       break;
  237.  
  238.     case OSERR_UNKNOWNMODE:
  239.       Quit ("Cannot open screen in this mode", 25);
  240.       break;
  241.  
  242.     case OSERR_NOCHIPMEM:
  243.       Quit ("Not enough CHIP memory", 25);
  244.       break;
  245.  
  246.     case OSERR_NOMEM:
  247.       Quit ("Not enough memory (CHIP or FAST)", 25);
  248.       break;
  249.  
  250.     default:
  251.       Quit ("Unspecified error opening screen", 25);
  252.       break;
  253.     }
  254.     }
  255.   /*
  256.    * StandardPalette() returns number of errors (see display24.c) I ignore
  257.    * the errors here and leave it to the client programs to deal with.
  258.    */
  259.   (VOID) StandardPalette (&(screen->ViewPort), FALSE);
  260.  
  261.   if ((menu = CreateMenus (prj_menu, GTMN_FrontPen, 1, TAG_DONE)) == NULL)
  262.     Quit ("could not build menu", 25);
  263.  
  264.   /*
  265.    * Open a backdrop window to which the above menu is attached.
  266.    */
  267.   if ((window = OpenWindowTags (NULL,
  268.                 WA_Top, screen->BarHeight + 1,
  269.                 WA_Height, screen->Height -
  270.                 (screen->BarHeight + 1),
  271.                 WA_CustomScreen, screen,
  272.                 WA_NewLookMenus, TRUE,
  273.                 WA_IDCMP, MENUPICK,
  274.          WA_Flags, ACTIVATE | BACKDROP | BORDERLESS | NOCAREREFRESH,
  275.                 TAG_END)) == NULL)
  276.     Quit ("could not open backdrop window", 25);
  277.  
  278.   /*
  279.    * visual info need to get proper look for menu
  280.    */
  281.   vi = GetVisualInfo (screen, TAG_END);
  282.   if (LayoutMenus (menu, vi, TAG_DONE) == NULL)
  283.     Quit ("could not layout menu", 25);
  284.   FreeVisualInfo (vi);
  285.   SetMenuStrip (window, menu);
  286.  
  287.   /*
  288.    * now go public
  289.    */
  290.   oldstatus = PubScreenStatus (screen, 0);
  291.  
  292.  
  293.   /*
  294.    * come forward if and window opens on this screen
  295.    */
  296.   SetPubScreenModes (POPPUBSCREEN);
  297.  
  298.   if (restart)
  299.     {
  300.       ReplyMsg ((struct Message *) newdims_msg);
  301.       restart = FALSE;
  302.     }
  303.   /*
  304.    * Now wait until told to quit by user (from menu) waiting of course for
  305.    * any visitors to leave.
  306.    */
  307.   psignal = 1 << messageport->mp_SigBit;
  308.   wsignal = 1 << window->UserPort->mp_SigBit;
  309.  
  310.   do
  311.     {
  312.       signal = Wait (wsignal | lastsignal | psignal);
  313.       if (signal & psignal)
  314.     {
  315.       newdims_msg = (struct TestMsg *) GetMsg (messageport);
  316.       width = newdims_msg->Width;
  317.       height = newdims_msg->Height;
  318.       lores = newdims_msg->Lores;
  319.       restart = TRUE;
  320.       /* NB. no reply to message until we have new screen */
  321.       if ((oldstatus = PubScreenStatus (screen,
  322.                         PSNF_PRIVATE)) & 1)
  323.         {
  324.           abort = TRUE;
  325.         }
  326.       else
  327.         {
  328.           closedown = TRUE;
  329.           EasyRequest (window, &failedES,
  330.                NULL,
  331.                "Cannot resize yet, there are other programs");
  332.         }
  333.     }
  334.       if (signal & lastsignal)
  335.     {
  336.  
  337.       if (closedown)
  338.         if ((oldstatus = PubScreenStatus (screen, PSNF_PRIVATE))
  339.         & 1)
  340.           abort = TRUE;
  341.     }
  342.       while (msg = (struct IntuiMessage *) GetMsg (window->UserPort))
  343.     {
  344.  
  345.       if (msg->Class == MENUPICK)
  346.         {
  347.           switch ((UWORD) MENU_USERDATA (ItemAddress (menu, msg->Code)))
  348.         {
  349.         case ABOUT:
  350.           EasyRequest (window, &failedES,
  351.                    NULL,
  352.                    COPYRIGHT_MESSAGE);
  353.           break;
  354.         case QUIT:
  355.           if ((oldstatus = PubScreenStatus (screen,
  356.                             PSNF_PRIVATE)) & 1)
  357.             {
  358.               abort = TRUE;
  359.             }
  360.           else
  361.             {
  362.               closedown = TRUE;
  363.               EasyRequest (window, &failedES,
  364.                    NULL,
  365.                   "Cannot Quit yet,\nthere are other programs");
  366.             }
  367.           break;
  368.         }
  369.         }
  370.       ReplyMsg ((struct Message *) msg);
  371.     }
  372.  
  373.   } while (abort == FALSE);
  374.  
  375.   /*
  376.    * Cleanup part 1. (part 2 is Cleanup())
  377.    */
  378.   ClearMenuStrip (window);
  379.  
  380.   CloseWindow (window);
  381.  
  382.   Cleanup ();
  383.  
  384. }
  385.  
  386. /*
  387.  * If another copy of this program is already running we just tell it what
  388.  * size of screen we want then exit.
  389.  */
  390.  
  391. void
  392. main ()
  393. {
  394.   LONG result[OPT_COUNT] =
  395.   {0, 0, 0};
  396.   struct RDArgs *rda;
  397.   BOOL running = FALSE;        /* set to true if we find another
  398.                  * copy running */
  399.   struct MsgPort *testport, *progport;
  400.   struct TestMsg *msg;
  401.  
  402.   /*
  403.    * Default values - 0 means Text overscan size ie Workbench like defaults
  404.    */
  405.   width = 0;
  406.   height = 0;
  407.   lores = FALSE;
  408.  
  409.   rda = ReadArgs (TEMPLATE, result, NULL);
  410.  
  411.   if (result[OPT_WIDTH])
  412.     width = *(LONG *) result[OPT_WIDTH];
  413.   if (result[OPT_HEIGHT])
  414.     height = *(LONG *) result[OPT_HEIGHT];
  415.   if (result[OPT_LORES])
  416.     lores = TRUE;
  417.   FreeArgs (rda);
  418.  
  419.   /*
  420.    * Check if copy of program running already
  421.    */
  422.   if (testport = CreatePort (NULL, NULL))
  423.     {
  424.       if (msg = AllocMem (sizeof (struct TestMsg), MEMF_PUBLIC | MEMF_CLEAR))
  425.     {
  426.       msg->msg.mn_ReplyPort = testport;
  427.       msg->msg.mn_Length = sizeof (struct TestMsg);
  428.       msg->Width = width;
  429.       msg->Height = height;
  430.       msg->Lores = lores;
  431.       Forbid ();
  432.       if (progport = FindPort (HAM8_ALBERT_NAME))
  433.         {
  434.           PutMsg (progport, (struct Message *) msg);
  435.           Permit ();
  436.           WaitPort (testport);
  437.           msg = (struct TestMsg *) GetMsg (testport);
  438.           running = TRUE;
  439.         }
  440.       Permit ();
  441.       FreeMem (msg, (ULONG) sizeof (struct TestMsg));
  442.     }
  443.       DeletePort (testport);
  444.     }
  445.   if (running)
  446.     return;
  447.  
  448.   messageport = CreatePort (HAM8_ALBERT_NAME, NULL);
  449.  
  450.   /*
  451.    * Go around this loop each time the screen is resized. al-backdrop.c
  452.    * uses this feature.
  453.    */
  454.   do
  455.     {
  456.       CreateScreen (lores, width, height);
  457.   } while (restart);
  458.   DeletePort (messageport);
  459. }
  460.